// 公共,私有与受保护的修饰符
// 在js的课程中我们学到默认情况下class内的属性和成员我们可以自由的访问,
// es6允许用户可以手动设置静态方法的方式避免继承

// 如果你对其他语言中的类比较了解, 就会注意到我们在之前的代码你并没有使用 public来做修饰；
// 例如C#，java 要求必须明确的使用 public指定成员是可见的
// 在Typescript和es6里 ， 成员都默认为public

// 手动设置public
class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name}moved${distanceInMeters}m.`);
    }
}
let o = new Animal("熊猫");
// console.log(o.name);// 输出 熊猫
// console.log(o.move(123));// 输出 熊猫移动了123m


// 当成员被标记成private 时，他就不能在声明它的类的外部访问
class Animal2 {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    private move(distanceInMeters: number) {
        console.log(`${this.name}moved${distanceInMeters}m.`);
    }
    private age: 19;
    public sayAge() {
        console.log(this.age);
    }
}
let o2 = new Animal2("熊猫");
// 报错 属性”move“为私有属性
// console.log(o2.move(123));
// // 报错 属性”age“为私有属性
// console.log(o2.age);
// o2.sayAge()


class Animal3 {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}
class Rhino extends Animal3 {
    constructor() { super("Rhino"); }
}
class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}
let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");

// console.log(animal);
// console.log(rhino);
// console.log(employee);

// animal = rhino;
// animal = employee;
// 错误：Animal 与 Employee 不兼容

// protected 保护修饰符
// protected 修饰符与 private修饰符的行为很相似，
// 但是有一点不同， protected成员在派生类中仍然可以访问
class Person{
    protected name:string;
    constructor(name:string){this.name = name;}
}
class Employee2 extends Person{
    private department:string;
    constructor(name:string,department:string){
        console.log(name,department);
        super(name)
        this.department = department
    }
    public getElevatorPitch(){
        return `Hello,my name is ${this.name} and I work in ${this.department}.`;
    }
}
let howard = new Employee2("howard","sales");
// 输出Hello，my name is howard and I work in Sales.
// 可以被派生的类进行调用
console.log(howard.getElevatorPitch());
// 错误， 还是不能在外部进行调用
// console.log(howard.name);


// readonly 只读修饰符
class Octopus{
    readonly name:string;
    readonly numberOfLegs:number=8;
    constructor(theName:string){
        this.name = theName;
    }
}
// 只读值被初始化，之后不在允许修改
let dad = new Octopus("Man with the 8 strong legs");
// 错误 name 是只读的
dad.name = "Man with 3-piece suit";
// 在创造构造函数时，我们有时不仅要限制某个变量后期设置值的时候要遵守的规则，
// 还要预设一个值的时候，就要用到参数属性，如上述代码中的numberOfLegs属性
// 即设置了值得类型也设置了值得初始值